home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / utility / journ201.zip / JOURNAL.C < prev    next >
Text File  |  1988-02-23  |  12KB  |  362 lines

  1. /******************************************************************************
  2. *
  3. * JOURNAL.C  Journal records and plays back Windows input along with the
  4. *            associated timing information.  The following keys are used
  5. *            to control Journal:
  6. *
  7. *       F7      Remove Journal from core
  8. *       F8      Prompt for a save file and begin recording
  9. *       F9      Stop recording and close the save file
  10. *       F10     Prompt for a save file and replay it
  11. *
  12. *       This is a modified version of the original Journal program uploaded
  13. *       by Microsoft.  Most of the information relating to the journalling
  14. *       filter functions was obtained by dissassembling the Windows 1.04
  15. *       kernel, and will probably change in the next version of Windows.
  16. *
  17. *       Modified by Daniel Smith                Aug 18 1987
  18. *                   Golden Software
  19. *                   807 14th Street
  20. *                   Golden, Colorado 80401
  21. *
  22. *       Modified for Windows 2.01               Feb 23 1988
  23. *
  24. *       This code will only work under Windows 2.01 or possibly higher.
  25. *       It will NOT work with Windows 1.x since all the callback function
  26. *       arguments have changed.
  27. *
  28. ******************************************************************************/
  29. #include <windows.h>
  30. #include <winexp.h>
  31. #include <direct.h>
  32. #include <string.h>
  33. #include "journal.h"
  34.  
  35. #define CEVENTSMAX  500                 /* Number of events to buffer */
  36.  
  37. typedef struct {                        /* Structure stored and saved */
  38.     unsigned message;                   /* during record and playback */
  39.     WORD  wParam1;
  40.     WORD  wParam2;
  41.     long  dt;
  42. } EVENT;
  43.  
  44. /* Function declarations */
  45.  
  46. int PASCAL WinMain(HANDLE,HANDLE,LPSTR,int);
  47. void ProcessCmd(WORD);
  48. int FAR PASCAL KeyHook(WORD,WORD,long);
  49. void FAR PASCAL Record(WORD,WORD,EVENT FAR *);
  50. DWORD FAR PASCAL Playback(WORD,WORD,EVENT FAR *);
  51. BOOL FAR PASCAL Dlgfn(HWND,unsigned,WORD,long);
  52. int WriteBuf(void);
  53. int ReadBuf(void);
  54. void Error(char *,char *);
  55.  
  56. char FileName[60];                      /* File to read and store events */
  57. long nbytesread;
  58. int bCmdLine;                           /* True if a command line was entered */
  59. BOOL fTurbo;                            /* TRUE if in turbo mode */
  60. HANDLE hJournalTask;                    /* Task handle for this program */
  61. HANDLE hInst;
  62. FARPROC lpfnKeyHook,lpfnKeyNext;        /* Keyboard hook for command keys */
  63. FARPROC lpfnRecord,lpfnRecordNext;      /* Journal hook for recording */
  64. FARPROC lpfnPlayback,lpfnPlaybackNext;  /* Journal hook for playing back */
  65. FARPROC lpfnDlg;
  66. BOOL fFirstRead;
  67. DWORD timeLastRead;
  68. EVENT *pevtRead,*pevtWrite;
  69. EVENT *pevtReadStop;
  70. BOOL fFirstWrite;
  71. DWORD timeLastWrite;
  72. EVENT rgevtJournal[CEVENTSMAX];         /* Buffer for events */
  73.  
  74. /******************************************************************************
  75. *
  76. * Main window function for journal
  77. *
  78. ******************************************************************************/
  79. int PASCAL WinMain(hInstance,hPrevInstance,CmdLine,CmdShow)
  80. HANDLE hInstance;
  81. HANDLE hPrevInstance;
  82. LPSTR CmdLine;
  83. int CmdShow;
  84. {
  85.    MSG msg;
  86.  
  87.    bCmdLine = *CmdLine;
  88.    if(hPrevInstance && !bCmdLine) return(0);
  89.    if(bCmdLine) lstrcpy(FileName,CmdLine);
  90.  
  91.    hInst = hInstance;
  92.    hJournalTask = GetCurrentTask();
  93.    fTurbo = FALSE;
  94.  
  95.    lpfnDlg = MakeProcInstance((FARPROC)Dlgfn,hInstance);
  96.    lpfnRecord = MakeProcInstance((FARPROC)Record,hInstance);
  97.    lpfnPlayback = MakeProcInstance((FARPROC)Playback,hInstance);
  98.    lpfnKeyHook = MakeProcInstance((FARPROC)KeyHook,hInstance);
  99.  
  100.    lpfnKeyNext = SetWindowsHook(WH_KEYBOARD,lpfnKeyHook);
  101.  
  102.    /* If program was started with a file name, assume it is a   */
  103.    /* previously created save file, and pass it on to the       */
  104.    /* playback code in the main loop.                           */
  105.  
  106.    if(bCmdLine) PostAppMessage(hJournalTask,WM_COMMAND,VK_F10,0L);
  107.  
  108.    while(GetMessage(&msg,0,0,0)){
  109.       if(msg.message == WM_COMMAND) ProcessCmd(msg.wParam);
  110.       else {
  111.          TranslateMessage(&msg);
  112.          DispatchMessage(&msg);
  113.       }
  114.    }
  115.    return(msg.wParam);
  116. }
  117.  
  118. /******************************************************************************
  119. *
  120. * Handles all WM_COMMAND messages sent to the application.
  121. *
  122. ******************************************************************************/
  123. void ProcessCmd(cmd)
  124. WORD cmd;
  125. {
  126.    int fh;
  127.  
  128.    switch(cmd){
  129.  
  130.    /* Prompt for save filename and start recording */
  131.    case VK_F8:
  132.       if(pevtRead==0 && pevtWrite==0){
  133.          if(DialogBox(hInst,MAKEINTRESOURCE(1),0,lpfnDlg)){
  134.             if((fh = _lcreat((LPSTR)FileName,0)) == -1)
  135.                Error("Journal Record","Unable to create file");
  136.             else {
  137.                pevtWrite = &rgevtJournal[0];
  138.                fFirstWrite = TRUE;
  139.                lpfnRecordNext = SetWindowsHook(WH_JOURNALRECORD,lpfnRecord);
  140.             }
  141.          }
  142.       }
  143.       break;
  144.  
  145.    /* Stop recording and close save file */
  146.    case VK_F9:
  147.       if(pevtWrite != 0){                 /* Ignore if not recording */
  148.          WriteBuf();
  149.          pevtWrite = 0;
  150.          SetWindowsHook(WH_JOURNALRECORD,0L);
  151.       }
  152.       break;
  153.  
  154.    /* Prompt for save filename and playback events */
  155.    case VK_F10:
  156.       if(pevtRead==0 && pevtWrite==0){
  157.          nbytesread = 0;
  158.          fFirstRead = TRUE;
  159.          if(bCmdLine || DialogBox(hInst,MAKEINTRESOURCE(2),0,lpfnDlg)){
  160.             if(ReadBuf()){
  161.                pevtRead = &rgevtJournal[0];
  162.                lpfnPlaybackNext = SetWindowsHook(WH_JOURNALPLAYBACK,lpfnPlayback);
  163.             }
  164.          }
  165.       }
  166.       break;
  167.  
  168.   /* Remove hooks and terminate */
  169.    case VK_F7:
  170.       SetWindowsHook(WH_KEYBOARD,0L);
  171.       PostQuitMessage(0);
  172.       break;
  173.    }
  174. }
  175.  
  176. /******************************************************************************
  177. *
  178. * Intercepts command keys from any application and sends the appropriate
  179. * command to this application.
  180. *
  181. ******************************************************************************/
  182. int FAR PASCAL KeyHook(code,wParam,lParam)
  183. WORD code,wParam;
  184. LONG lParam;
  185. {
  186.    if(HIWORD(lParam) & 0x8000){           /* Up transition of key */
  187.       switch(wParam){
  188.       case VK_F8:
  189.       case VK_F9:
  190.       case VK_F10:
  191.       case VK_F7:
  192.          PostAppMessage(hJournalTask,WM_COMMAND,wParam,0L);
  193.          return(1);
  194.       }
  195.    }
  196.    return(0);
  197. }
  198.  
  199. /******************************************************************************
  200. *
  201. * Filter function to record all input events and save in a file
  202. *
  203. ******************************************************************************/
  204. void FAR PASCAL Record(dum1,dum2,lpevt)
  205. WORD dum1,dum2;
  206. EVENT FAR *lpevt;
  207. {
  208.    int fh;
  209.  
  210.    if(pevtWrite >= &rgevtJournal[CEVENTSMAX]){
  211.       if(!WriteBuf()){
  212.          SetWindowsHook(WH_JOURNALRECORD,0L);
  213.          pevtWrite = 0;
  214.          return;
  215.       }
  216.    }
  217.  
  218.    *pevtWrite = *lpevt;
  219.    if(fFirstWrite){
  220.       fFirstWrite = FALSE;
  221.       timeLastWrite = pevtWrite->dt;
  222.    }
  223.  
  224.    pevtWrite->dt -= timeLastWrite;              /* Map to delta time */
  225.    timeLastWrite = lpevt->dt;                   /* Remember time of last write */
  226.    pevtWrite++;
  227. }
  228.  
  229. /******************************************************************************
  230. *
  231. * Filter function to insert an event into the Windows system queue
  232. *
  233. ******************************************************************************/
  234. DWORD FAR PASCAL Playback(code,lotime,lpevt)
  235. WORD code,lotime;
  236. EVENT FAR *lpevt;
  237. {
  238.    long dt;
  239.  
  240.    switch(code){
  241.    case 1:                              /* Called from GetNextSysMsg */
  242.       if(fFirstRead){                   /* Save current start time */
  243.          timeLastRead = lpevt->dt;
  244.          fFirstRead = FALSE;
  245.       }
  246.       dt = pevtRead->dt - (lpevt->dt - timeLastRead);
  247.       *lpevt = *pevtRead;               /* Copy event to Windows buffer */
  248.       if(!fTurbo && dt>0) return(dt);   /* Not ready yet: return time left */
  249.       lpevt->dt += timeLastRead;        /* Convert relative to absolute time */
  250.       return(0L);                       /* Time to process event */
  251.       break;
  252.  
  253.    case 2:                              /* Called from SkipSysMsg */
  254.       timeLastRead += pevtRead->dt;     /* Update current time */
  255.       pevtRead++;                       /* Point to next event */
  256.       if(pevtRead == pevtReadStop){     /* End of stored events */
  257.          if(ReadBuf()){
  258.             pevtRead = &rgevtJournal[0];
  259.          } else {
  260.             pevtRead = 0;
  261.             SetWindowsHook(WH_JOURNALPLAYBACK,0L);
  262.             if(bCmdLine)
  263.                PostAppMessage(hJournalTask,WM_COMMAND,VK_F7,0L);
  264.          }
  265.       }
  266.       return(0L);                       /* Not used by this function call */
  267.       break;
  268.  
  269.    default:
  270.       Error("Journal Playback", "Unknown code");
  271.       return(0L);
  272.    }
  273. }
  274.  
  275. /******************************************************************************
  276. *
  277. * Handles the open and save dialog boxes for journal.
  278. *
  279. ******************************************************************************/
  280. BOOL FAR PASCAL Dlgfn(hDlg,message,wParam,lParam)
  281. HWND hDlg;
  282. unsigned message;
  283. WORD wParam;
  284. LONG lParam;
  285. {
  286.    char tempbuf[49];
  287.  
  288.    if(message == WM_COMMAND){                   /* If OK was pressed */
  289.       if(wParam==IDOK || wParam==IDTURBO){
  290.          GetDlgItemText(hDlg,IDCONST,FileName,30);
  291.          getcwd(tempbuf,49);
  292.          if(tempbuf[strlen(tempbuf)-1] != '\\') lstrcat(tempbuf,"\\");
  293.          lstrcat(tempbuf,FileName);
  294.          lstrcpy(FileName,tempbuf);
  295.          fTurbo = (wParam == IDTURBO);
  296.          EndDialog(hDlg,TRUE);
  297.          return(TRUE);
  298.       }
  299.       if(wParam == IDCANCEL){
  300.          EndDialog(hDlg,FALSE);
  301.          return(TRUE);
  302.       }
  303.    } else if(message == WM_INITDIALOG) return(TRUE);
  304.       else return(FALSE);
  305. }
  306.  
  307. /******************************************************************************
  308. *
  309. * Writes the event buffer to the disk file
  310. *
  311. ******************************************************************************/
  312. int WriteBuf()
  313. {
  314.    int fh;
  315.  
  316.    if((fh = _lopen(FileName,READ_WRITE)) == -1){
  317.       Error("Journal Record","Unable to open file");
  318.       return(0);
  319.    }
  320.    _llseek(fh,0L,2);                            /* Go to end of file... */
  321.    _lwrite(fh,(LPSTR)&rgevtJournal[0],
  322.            (pevtWrite-&rgevtJournal[0])*sizeof(EVENT));
  323.    _lclose(fh);
  324.    pevtWrite = &rgevtJournal[0];
  325.    return(1);
  326. }
  327. /******************************************************************************
  328. *
  329. * Fills the event buffer from the playback file
  330. *
  331. ******************************************************************************/
  332. int ReadBuf()
  333. {
  334.    int fh,nbr;
  335.  
  336.    if((fh = _lopen(FileName,READ)) != -1){
  337.       nbytesread = _llseek(fh,(LONG)nbytesread,0);
  338.       nbr = _lread(fh,(LPSTR)&rgevtJournal[0],CEVENTSMAX*sizeof(EVENT));
  339.       _lclose(fh);
  340.       if(nbr == -1) goto error;
  341.       pevtReadStop = &rgevtJournal[nbr/sizeof(EVENT)];  /* One beyond last */
  342.       nbytesread += nbr;
  343.       return(nbr);
  344.    }
  345.  
  346.     error:
  347.     Error("Journal Playback","Unable to Read File");
  348.     return(0);
  349. }
  350.  
  351. /******************************************************************************
  352. *
  353. * Displays an error message in a message box
  354. *
  355. ******************************************************************************/
  356. void Error(pszcap,pszmsg)
  357. char *pszcap;
  358. char *pszmsg;
  359. {
  360.    MessageBox(0,pszmsg,pszcap,MB_SYSTEMMODAL | MB_OK | MB_ICONEXCLAMATION);
  361. }
  362.